
/**
 * 记录每个选手的是否完成情况等
 */

import Timer from "../../../common/timer/Timer";

export default class ScoreBoard {
	timer = new Timer();
	title = '四强争霸';
	presetEnable = false;

	boards = [
		new PlayerBoard(1, '比特队', this),
		new PlayerBoard(2, '洛克队', this),
		new PlayerBoard(3, '艾迪队', this),
		new PlayerBoard(4, '梅塔队', this),
	];

	// 所有 callback
	/** @type {function (number, string) => } 输入是 playerNo 和 name */ onPlayerNameUpdate;
	/** @type {function (string) => } 输入是 title */ onTitleUpdate;
	/** @type {function () => } 如果从头开始会发送 */ onTimerStart;
	/** @type {function () => } 只要开始就发送, 可能和 onTimerStart 一起触发 */ onTimerPlay;
	/** @type {function () => } */ onTimerStop;
	/** @type {function () => } */ onTimerPause;
	/** @type {function () => } */ onTimerReset;

	/** @type {function (number) => } */ onPlayerStart;
	/** @type {function (number) => } */ onPlayerStop;
	/** @type {function (number) => } */ onPlayerFinish;
	/** @type {function (number) => } */ onPlayerReset;

	tick() {
		this.timer.tick();

		// preset
		if (!this.presetEnable) {
			return;
		}
		const currentTime = this.timer.delta;
		this.boards.forEach(p => {
			p.preset && currentTime > p.preset && !p.isFinished() && this.doRecord(p.playerNo, p.preset);
		});
	}

	updatePlayerName(playerNo, name) {
		this.findPlayer(playerNo).updateName(name);
	}

	updateTitle(title) {
		this.title = String(title);
		this.onTitleUpdate && this.onTitleUpdate(this.title);
	}

	timerStart() {
		const timer = this.timer;
		const delta = timer.delta;
		timer.play();
		if (delta == 0) {
			this.onTimerStart && this.onTimerStart();
		}
		this.onTimerPlay && this.onTimerPlay();
		// 只要不是结束的玩家, 都开始
		this.boards.forEach(p => p.isFinished() || p.start());
	}

	timerStop() {
		this.timer.stop();
		this.onTimerStop && this.onTimerStop();
		// 只要不是已经结束的玩家, 都触发结束 (未计时)
		this.boards.forEach(p => p.isFinished() || p.stop());
	}

	timerPause() {
		this.timer.pause();
		this.onTimerPause && this.onTimerPause();
		// 只要不是已经结束的玩家, 都触发结束 (未计时)
		this.boards.forEach(p => p.isFinished() || p.stop());
	}

	timerUndoPause() {
		this.timer.undoPause();
		this.onTimerPlay && this.onTimerPlay();
		// 只要不是已经结束的玩家, 都开始
		this.boards.forEach(p => p.isFinished() || p.start());
	}

	findPlayer(playerNo) {
		let index = this.boards.findIndex(p => p.playerNo === playerNo);
		if (index < 0) {
			throw { message : '找不到玩家: ' + playerNo };
		}
		return this.boards[index];
	}

	/**
	 * 全部结束了吗, 弃权的不算
	 */
	allFinished() {
		return this.boards.reduce((count, p) => p.isFinished() ? count + 1: count, 0) == this.boards.length;
	}

	timerReset() {
		this.timer.reset();
		this.onTimerReset && this.onTimerReset();
		this.boards.forEach(b => b.reset());
	}

	/**
	 * @param {number} playerNo 1-4
	 * @param {number} score 可以设定成功的时间, ms
	 */
	doRecord(playerNo, score = (this.timer.delta | 0)) {
		this.findPlayer(playerNo).doFinish(score);
		if (this.allFinished()) {
			this.timerStop();
		}
	}

	undoRecord(playerNo) {
		this.findPlayer(playerNo).start();
		if (this.timer.isFinished()) {
			this.timer.undoPause();
			this.onTimerPlay && this.onTimerPlay();
		}
	}

	/**
	 * 某玩家宣布弃权
	 * @param {number} playerNo
	 */
	waiver(playerNo) {
		this.findPlayer(playerNo).waiver();
		if (this.allFinished()) {
			this.timerStop();
		}
	}

	removePreset(playerNo) {
		this.findPlayer(playerNo).preset = 0;
		this.presetEnable = this.boards.filter(p => p.score != 0).length > 0;
	}

	preset(playerNo, score) {
		this.findPlayer(playerNo).preset = parseInt(score);
		this.presetEnable = true;
	}
}

class PlayerBoard {
	constructor(playerNo, name, parent) {
		/** @type {number} */ this.playerNo = playerNo;
		/** @type {string} */ this.name = name;
		/** @type {ScoreBoard} */ this.parent = parent;

		/** 0:表示没结束. -1:表示不参加或弃权  其它就是 new Date() */ this.finish = 0;
		/** @type {number} 毫秒计的分数, null 表示没结束, 0 表示弃权 / 已结束但没成绩 */ this.score = null;
		/** @type {number} 新需求, 鸽鸽想让某些计时器到某个时间点自动停下. 0 表示没设置 */
		this.preset = 0;
	}

	updateName(name) {
		this.name = String(name);
		this.parent.onPlayerNameUpdate && this.parent.onPlayerNameUpdate(this.playerNo, this.name);
	}

	reset() {
		this.finish = 0;
		this.score = null;
		this.preset = 0;
		this.parent.onPlayerReset && this.parent.onPlayerReset(this.playerNo);
	}

	start() {
		this.finish = 0;
		this.score = null;
		this.parent.onPlayerStart && this.parent.onPlayerStart(this.playerNo);
	}

	stop() {
		this.finish = Date.now();
		this.score = 0;
		this.parent.onPlayerStop && this.parent.onPlayerStop(this.playerNo);
	}

	/**
	 * @param {number} score 计时示数, ms
	 */
	doFinish(score = this.parent.timer.delta) {
		this.finish = Date.now();
		this.score = score;
		this.parent.onPlayerFinish && this.parent.onPlayerFinish(this.playerNo);
	}

	waiver() {
		this.finish = -1;
		this.score = 0;
		this.parent.onPlayerStop && this.parent.onPlayerStop(this.playerNo);
	}

	undoFinish() {
		this.finish = 0;
		this.score = null;
		this.parent.onPlayerStart && this.parent.onPlayerStart(this.playerNo);
	}

	/**
	 * 是否是弃权 / 跑完了 (有成绩)
	 */
	isFinished() {
		return this.isStopped() && this.score > 0;
	}

	/**
	 * 有可能没跑完暂停, 总之不在跑
	 */
	isStopped() {
		return this.finish != 0;
	}

	isWaivered() {
		return this.finish == -1;
	}
}

